<template>
  <canvas ref="cvsRef" :width="props.width" :height="props.height"></canvas>
</template>

<script setup lang="ts">
import { nextTick, onBeforeUnmount, onMounted, ref, watchEffect } from "vue";

// props width height
const props = defineProps({
  width: {
    type: Number,
    default: 375,
  },
  height: {
    type: Number,
    default: 664,
  },
  lineWidth: {
    type: Number,
    default: 1,
  },
  strokeStyle: {
    type: String,
    default: 1,
  },
  eraser: {
    type: Boolean,
    default: false,
  },
});

const emits = defineEmits(["onMouseup"]);

const cvsRef = ref<HTMLCanvasElement | null>(null);
const cvsRect = ref({
  left: 0,
  top: 0,
});
const ctx = ref<CanvasRenderingContext2D | null>(null);
const isDrawing = ref(false);
const isEraser = ref(false);

watchEffect(() => {
  isEraser.value = props.eraser;
});

onMounted(() => {
  nextTick(() => {
    initCanvas();
  });

  window.addEventListener("resize", initCanvas);
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", initCanvas);
});

// 初始化canvas绑定鼠标按下 移动 和 松开事件
const initCanvas = () => {
  if (!cvsRef.value) return;
  const cvs = cvsRef.value;
  cvsRect.value = cvsRef.value.getBoundingClientRect();
  const ctx = cvs.getContext("2d");
  if (!ctx) return;

  cvs.addEventListener("mousedown", (e) => {
    handleStartDraw(ctx, e.offsetX, e.offsetY);
  });
  cvs.addEventListener("mousemove", (e) => {
    handleMoveDraw(ctx, e.offsetX, e.offsetY);
  });
  cvs.addEventListener("mouseup", () => {
    handleEndDraw();
  });

  cvs.addEventListener(
    "touchstart",
    (e) => {
      handleStartDraw(
        ctx,
        e.touches[0].clientX - cvsRect.value.left,
        e.touches[0].clientY - cvsRect.value.top
      );
    },
    {
      passive: false,
    }
  );

  cvs.addEventListener(
    "touchmove",
    (e) => {
      if (isDrawing.value) {
        handleMoveDraw(
          ctx,
          e.touches[0].clientX - cvsRect.value.left,
          e.touches[0].clientY - cvsRect.value.top
        );
      }
    },
    {
      passive: false,
    }
  );

  cvs.addEventListener(
    "touchend",
    () => {
      handleEndDraw();
    },
    {
      passive: false,
    }
  );
};

// 点击按钮实现画布橡皮擦功能，只擦除部分位置的功能
const clearPartRect = (ctx: CanvasRenderingContext2D, x: number, y: number) => {
  ctx.clearRect(x, y, 100, 100);
};

const startDraw = (ctx: CanvasRenderingContext2D, x: number, y: number) => {
  isDrawing.value = true;
  ctx.lineWidth = props.lineWidth;
  ctx.strokeStyle = props.strokeStyle;
  ctx.beginPath();
  ctx.moveTo(x, y);
};

const moveDraw = (ctx: CanvasRenderingContext2D, x: number, y: number) => {
  if (isDrawing.value) {
    ctx.lineTo(x, y);
    ctx.stroke();
  }
};

const endDraw = () => {
  isDrawing.value = false;
};

const handleStartDraw = (
  ctx: CanvasRenderingContext2D,
  x: number,
  y: number
) => {
  console.log(isEraser.value);
  if (isEraser.value) {
    clearPartRect(ctx, x, y);
  } else {
    startDraw(ctx, x, y);
  }
};

const handleMoveDraw = (
  ctx: CanvasRenderingContext2D,
  x: number,
  y: number
) => {
  console.log(isEraser.value, x, y);
  if (isEraser.value) {
    clearPartRect(ctx, x, y);
  } else {
    moveDraw(ctx, x, y);
  }
};

const handleEndDraw = () => {
  if (isEraser.value) {
    emits("onMouseup");
  } else {
    endDraw();
  }
};

// 清空画布
const clearCanvas = () => {
  if (!cvsRef.value) return;
  const ctx = cvsRef.value.getContext("2d");
  if (!ctx) return;
  ctx.clearRect(0, 0, props.width, props.height);
};

// 保存画布
const saveCanvas = () => {
  if (!cvsRef.value) return;
  const dataURL = cvsRef.value.toDataURL("image/png");
  // 创建a标签
  const a = document.createElement("a");
  // 设置a标签的属性
  a.href = dataURL;
  a.download = "canvas.png";
  // 触发下载
  a.click();
  // 释放内存
  a.remove();
};

defineExpose({
  clearCanvas,
  saveCanvas,
});
</script>

<style lang="scss" scoped></style>
